#include "mat2.h"
#include "dmat2.h"

namespace libvec
{
  mat2::mat2()
  {
    vec2 v(0);

    this->v1 = v;
    this->v2 = v;
  }

  mat2::mat2(dmat2 m)
  {
    this->v1 = m.v1;
    this->v2 = m.v2;
  }

  mat2::mat2(float value)
  {
    this->v1.x = value;
    this->v2.y = value;
  }

  mat2::mat2(float n11, float n12, float n21, float n22)
  {
    this->v1.x = n11;
    this->v2.x = n12;

    this->v1.y = n21;
    this->v2.y = n22;
  }

  mat2::mat2(vec2 v1, vec2 v2)
  {
    this->v1 = v1;
    this->v2 = v2;
  }

  vec2 &mat2::operator[](int index)
  {
    static vec2 empty;

    switch (index)
    {
      case 0:
        return this->v1;

      case 1:
        return this->v2;
    }

    return empty;
  }

  mat2 mat2::operator=(mat2 m)
  {
    this->v1 = m.v1;
    this->v2 = m.v2;

    return *this;
  }

  bool mat2::operator==(mat2 m)
  {
    return (this->v1 == m.v1) && (this->v2 == m.v2);
  }

  bool mat2::operator!=(mat2 m)
  {
    return (this->v1 != m.v1) || (this->v2 != m.v2);
  }

  mat2 &mat2::operator+()
  {
    return *this;
  }

  mat2 &mat2::operator-()
  {
    static mat2 out;

    out.v1 = -this->v1;
    out.v2 = -this->v2;

    return out;
  }

  mat2 mat2::operator+(mat2 m)
  {
    static mat2 out;

    out.v1 = this->v1 + m.v1;
    out.v2 = this->v2 + m.v2;

    return out;
  }

  mat2 mat2::operator+=(mat2 m)
  {
    this->v1 += m.v1;
    this->v2 += m.v2;

    return *this;
  }

  mat2 mat2::operator-(mat2 m)
  {
    static mat2 out;

    out.v1 = this->v1 - m.v1;
    out.v2 = this->v2 - m.v2;

    return out;
  }

  mat2 mat2::operator-=(mat2 m)
  {
    this->v1 -= m.v1;
    this->v2 -= m.v2;

    return *this;
  }

  vec2 mat2::operator*(vec2 v)
  {
    static vec2 out;

    out.x = this->v1.x*v.x + this->v2.x*v.y;
    out.y = this->v1.y*v.x + this->v2.y*v.y;

    return out;
  }

  mat2 mat2::operator*(mat2 m)
  {
    static mat2 out;

    out.v1.x = this->v1.x*m.v1.x + this->v2.x*m.v1.y;
    out.v2.x = this->v1.x*m.v2.x + this->v2.x*m.v2.y;

    out.v1.y = this->v1.y*m.v1.x + this->v2.y*m.v1.y;
    out.v2.y = this->v1.y*m.v2.x + this->v2.y*m.v2.y;

    return out;
  }

  mat2 mat2::operator*=(mat2 m)
  {
    static mat2 out;

    out.v1.x = this->v1.x*m.v1.x + this->v2.x*m.v1.y;
    out.v2.x = this->v1.x*m.v2.x + this->v2.x*m.v2.y;

    out.v1.y = this->v1.y*m.v1.x + this->v2.y*m.v1.y;
    out.v2.y = this->v1.y*m.v2.x + this->v2.y*m.v2.y;

    this->v1 = out.v1;
    this->v2 = out.v2;

    return out;
  }

  mat2 mat2::operator*(float scale)
  {
    static mat2 out;

    out.v1 = this->v1 * scale;
    out.v2 = this->v2 * scale;

    return out;
  }

  mat2 mat2::operator*=(float scale)
  {
    this->v1 *= scale;
    this->v2 *= scale;

    return *this;
  }

  mat2 mat2::operator/(float scale)
  {
    static mat2 out;

    out.v1 = this->v1 / scale;
    out.v2 = this->v2 / scale;

    return out;
  }

  mat2 mat2::operator/=(float scale)
  {
    this->v1 /= scale;
    this->v2 /= scale;

    return *this;
  }
}

